package com.jxd.ordering.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jxd.ordering.dao.AdminMapper;
import com.jxd.ordering.dao.EmpMapper;
import com.jxd.ordering.dao.UserMapper;
import com.jxd.ordering.exception.serviceexception.AccountExistException;
import com.jxd.ordering.exception.serviceexception.PwdErrorException;
import com.jxd.ordering.exception.serviceexception.UserNotFoundException;
import com.jxd.ordering.model.Admin;
import com.jxd.ordering.model.Emp;
import com.jxd.ordering.model.User;
import com.jxd.ordering.service.IPermissionService;
import com.jxd.ordering.service.IUserService;
import com.jxd.ordering.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName UserServiceImpl
 * @Description TODO
 * @Author Ankailong
 * @Date 2022/9/28
 * @Version 1.0
 */
@Service
public class UserServiceImpl implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private EmpMapper empMapper;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private IPermissionService permissionService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 新增用户信息
     * @param user 用户实体类
     * @return 是否新增成功
     */
    @Override
    public boolean addUser(User user) throws AccountExistException {
        if (userMapper.selectUserByAccount(user.getAccount()) != null) {
            throw new AccountExistException();
        }

        user.setPwd(passwordEncoder.encode(user.getPwd()));
        return userMapper.insertUser(user);
    }

    /**
     * 修改用户信息
     * @param user 用户实体类
     * @return 是否修改成功
     */
    @Override
    @Transactional
    public boolean editUser(User user) {
        //开启事务
        if (user.getPermission() < 3) {
            return empMapper.updateEnameByEmpno(user.getUserno(), user.getUname()) && userMapper.updateUser(user);
        } else {
            Admin admin = new Admin(user.getUserno(), user.getUname(), user.getUserid());
            adminMapper.updateAdmin(admin);
            userMapper.updateUser(user);
            return true;
        }
    }

    /**
     * 修改密码
     * @param userid 用户id
     * @param pwd 新密码
     * @return 是否修改成功
     */
    @Override
    public boolean editPassword(int userid, String pwd) {
        pwd = passwordEncoder.encode(pwd);
        return userMapper.updatePassword(userid, pwd);
    }

    /**
     * 批量删除用户信息
     * @param userids 用户编号数组
     * @return 是否删除成功
     */
    @Override
    @Transactional
    public boolean delUser(int[] userids) {
        //开启事务
        List<Integer> empnos = new ArrayList<>();
        List<Integer> adminnos = new ArrayList<>();

        for (int userid : userids) {
            Map user = userMapper.selectUserByUserid(userid);
             if (Integer.parseInt(user.get("permission").toString()) < 3) {
                 empnos.add(getUsernoByUserid(userid));
             } else {
                 adminnos.add(getUsernoByUserid(userid));
             }
        }

        userMapper.deleteUser(userids);
        if (empnos.size() > 0) {
            empMapper.deleteEmp(empnos.stream().mapToInt(Integer::intValue).toArray());
        }
        if (adminnos.size() > 0) {
            adminMapper.deleteAdmin(adminnos.stream().mapToInt(Integer::intValue).toArray());
        }
        return true;
    }

    /**
     * 分页查询全部用户信息
     * @param queryMap 包含 int page, int limit, String uname, int type（1用户 2管理员）
     * @return 查询结果
     */
    @Override
    public Map<String, Object> getUserByPage(Map<String, String> queryMap) {
        String page = queryMap.get("page");
        String limit = queryMap.get("limit");

        Map<String, Object> map = new HashMap(4);
        if(page != null && limit != null){
            IPage<User> pages = new Page(Integer.parseInt(page),Integer.parseInt(limit));
            userMapper.selectUserByPage(pages, queryMap);

            map.put("count",pages.getTotal());
            map.put("data",pages.getRecords());

            map.put("code",0);
            return map;
        }else{
            map.put("data", (Object)null);
            map.put("code", "500");
            map.put("msg", "参数不符");
            map.put("count", (Object)null);
            return map;
        }
    }

    /**
     * 按用户id查询用户信息
     * @param userid 用户编号
     * @return 查询结果
     */
    @Override
    public Map<String, Object> getUserByUserid(int userid) {
        return userMapper.selectUserByUserid(userid);
    }

    /**
     * 按用户名查询用户信息
     * @param account 用户名
     * @return 查询结果
     */
    @Override
    public User getUserByAccount(String account) {
        return userMapper.selectUserByAccount(account);
    }

    /**
     * 按用户id查询用户权限等级
     * @param userid 用户编号
     * @return 查询结果
     */
    @Override
    public String getPermissionByUserid(int userid) {
        Map map = userMapper.selectUserByUserid(userid);
        String permission = map.get("permission").toString();
        return permission;
    }

    /**
     * 按用户id查询用户编号
     * @param userid 用户id
     * @return 查询结果
     */
    @Override
    public int getUsernoByUserid(int userid) {
        return (int)userMapper.selectUserByUserid(userid).get("userno");
    }

    /**
     * 按用户id查询用户部门编号
     * @param userid 用户编号
     * @return 查询结果
     */
    @Override
    public int getDeptnoByUserid(int userid) {
        int userno =  (int)userMapper.selectUserByUserid(userid).get("userno");
        return empMapper.selectEmpByEmpno(userno).getDeptno();
    }

    /**
     * 登录
     * @param account 用户名
     * @param pwd 密码
     * @return 用户信息 包含 uname, permission, headshot, userno, token
     */
    @Override
    public Map<String, Object> login(String account, String pwd) throws UserNotFoundException, PwdErrorException {
        Map<String, Object> result = new HashMap<>();
        User user = userMapper.selectUserByAccount(account);

        if (user == null) {
            throw new UserNotFoundException();
        }

        if (user.getPermission() < 3) {
            result.put("deptno", empMapper.selectEmpByEmpno(user.getUserno()).getDeptno());
        }

        if (passwordEncoder.matches(pwd, user.getPwd())) {
            result.put("userid", user.getUserid());
            result.put("uname", user.getUname());
            result.put("permission", user.getPermission());
            result.put("headshot", user.getHeadshot());
            result.put("userno", user.getUserno());
            result.put("routes", permissionService.getPermissionByLevel(user.getPermission()));

            String token = JwtUtil.createToken(user.getUserid()+"");
            result.put("token", token);
            return result;
        } else {
            throw new PwdErrorException();
        }
    }

    /**
     * 注册
     * @param map 包含 account,pwd,uname,sex,tel,deptno,job
     *            密码字符不能包含 % ^ [ ] { }
     * @return 用户信息 包含 account,pwd
     */
    @Override
    @Transactional
    public Map<String, Object> register(Map<String, String> map) throws AccountExistException {
        //开启事务
        Map<String, Object> result = new HashMap<>();

        if (userMapper.selectUserByAccount(map.get("account")) != null) {
            throw new AccountExistException();
        }

        Emp emp = new Emp(null ,map.get("uname"), Integer.parseInt(map.get("sex")), map.get("tel"),
                Integer.parseInt(map.get("deptno")), Integer.parseInt(map.get("job")), null);
        User user = new User(null, map.get("account"), map.get("pwd"), map.get("uname"),
                Integer.parseInt(map.get("job")), null, null);
        empMapper.insertEmp(emp);
        emp = empMapper.selectEmpByEmpno(emp.getEmpno());
        user.setUserno(emp.getEmpno());

        addUser(user);
        result.put("account", map.get("account"));
        result.put("pwd", map.get("pwd"));

        emp.setUserid(user.getUserid());
        empMapper.updateEmp(emp);
        return result;
    }
}
